package vg.modules.notepad.components.connectorComponent;

import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import vg.services.main_manager.MainManager;
import vg.services.plugin_manager.event_and_request.event.UIEventCreateNewConnection;
import vg.services.plugin_manager.event_and_request.event.UIEventDeleteConnection;
import vg.services.plugin_manager.realization.PluginParameter;
import vg.services.user_interface_manager.additional_swing_components.ValueComboBox;

/**
 * This class realizes connector between graph model and current file.
 * All methods of this class by need called from EDT only!!!
 * @author tzolotuhin
 */
public class Connector extends JDialog {
	private static final long serialVersionUID = 1l;
	// Data
	private static final AtomicInteger counterId = new AtomicInteger(0);
	private final PluginParameter param;
	// Components
	private final JLabel connectionLabel, graphLabel, anchorLabel;
	private final JTextField connectionField;
	private final GraphComboBox graphComboBox;
	private final ValueComboBox anchorComboBox;
	// Data
	private int fileId;
	private int connectionId = -1;
	// Buttons
	private final JButton okButton, cancelButton;
	/**
	 * Constructor.
	 * @param param - feed back between user interface and connector.
	 */
	public Connector(final PluginParameter param, final Frame parent) {
		super(parent, "Connector", true);
		// save input parameters
		this.param = param;
		// create components
		this.okButton = new JButton("Ok");			
		this.cancelButton = new JButton("Cancel");
		
		this.connectionLabel = new JLabel("Connection name: ");
		this.graphLabel = new JLabel("Graph model: ");
		this.anchorLabel = new JLabel("Anchor: ");
		this.anchorComboBox = new ValueComboBox();
		this.connectionField = new JTextField("");
		this.graphComboBox = new GraphComboBox();
		// add listeners
		this.cancelButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Connector.this.setVisible(false);
			}
		});
		
		this.graphComboBox.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Connector.this.anchorComboBox.removeAllItems();
				Integer graphId = (Integer)graphComboBox.getSelectedObject();
				if(graphId != null) {
					String request = "select distinct a.name " + 
							  		 "from com_graph_subgraph cgs, com_subgraph_vertex csv, com_vertex_attribute cva, com_subgraph_edge cse, com_edge_attribute cea, attribute a " + 
							  		 "where cgs.db_id_graph = " + graphId.toString() + " and " +
							  		 "((cgs.db_id_subgraph = csv.db_id_subgraph and csv.db_id_vertex = cva.db_id_vertex and cva.db_id_attribute = a.db_id) or " + 
							  		 "(cgs.db_id_subgraph = cse.db_id_subgraph and cse.db_id_edge = cea.db_id_edge and cea.db_id_attribute = a.db_id));";
					
					List<List<Object>> result = param.graphDataBase.executeSQLRequest(request);
					if (result != null) {
						Iterator<List<Object>> it = result.iterator();
						while (it.hasNext()) {
							String name = (String) it.next().get(0);
							anchorComboBox.addItem(name);
						}
					}

				}
			}
		});
		
		this.okButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String locConnectName = connectionField.getText();
				String locAnchor = anchorComboBox.getSelectedItem();
				Integer locGraphId = (Integer)graphComboBox.getSelectedObject();
				String locGraphName = (String)graphComboBox.getSelectedTitle();
				if(locConnectName == null || locConnectName.length() == 0) {
					MainManager.windowMessage.warningMessage("Warning: Uncorrect connect name. Example: name_128.", "Warning");
					return;						
				}
				if(locAnchor == null || !anchorComboBox.isContains(locAnchor)) {
					MainManager.windowMessage.warningMessage("Warning: Uncorrect anchor.", "Warning");
					return;
				}
				if(locGraphId == null || locGraphId < 0) {
					MainManager.windowMessage.warningMessage("Warning: Uncorrect graph.", "Warning");
					return;				
				}
				if(connectionId < 0) {
					UIEventCreateNewConnection event = new UIEventCreateNewConnection(getNextId(), locConnectName, locAnchor, locGraphId, locGraphName, fileId);
					param.userInterfaceManager.sendEvent(event);
				} else {
					UIEventDeleteConnection event1 = new UIEventDeleteConnection(connectionId);
					param.userInterfaceManager.sendEvent(event1);
					UIEventCreateNewConnection event2 = new UIEventCreateNewConnection(connectionId, locConnectName, locAnchor, locGraphId, locGraphName, fileId);
					param.userInterfaceManager.sendEvent(event2);
				}
				Connector.this.setVisible(false);				
			}
		});
		this.setLayout(new GridBagLayout());
		this.setTitle("Connector");
		this.setResizable(false);
		this.setDefaultCloseOperation(HIDE_ON_CLOSE);
		this.setSize(400, 220);
		// pack ui
		GridBagConstraints gbc = null;
		gbc = new GridBagConstraints(0,0, 1,1, 0,0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0,0);
		this.add(this.connectionLabel, gbc);
		gbc = new GridBagConstraints(1,0, 1,1, 1,0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0,0);
		this.add(this.connectionField, gbc);
		
		gbc = new GridBagConstraints(0,1, 1,1, 0,0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0,0);
		this.add(this.graphLabel, gbc);
		gbc = new GridBagConstraints(1,1, 1,1, 1,0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0,0);
		this.add(this.graphComboBox.getView(), gbc);

		gbc = new GridBagConstraints(0,2, 1,1, 0,0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0,0);
		this.add(this.anchorLabel, gbc);
		gbc = new GridBagConstraints(1,2, 1,1, 1,0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0,0);
		this.add(this.anchorComboBox.getView(), gbc);

		gbc = new GridBagConstraints(0,3, 1,1, 1,0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0,0);
		this.add(this.okButton, gbc);

		gbc = new GridBagConstraints(1,3, 1,1, 1,0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0,0);
		this.add(this.cancelButton, gbc);
					
		this.setVisible(false);
		super.setLocationRelativeTo(parent);
	}
	/**
	 * This method helps to user create new connection
	 * between graph model and additional text file.
	 */
	public void open(final int fileId, final String connectionName) {
		// load data from model
		this.graphComboBox.removeAllItems();
		String request = "select s1.db_id, s1.name from graph s1;";
		List<List<Object>> result = param.graphDataBase.executeSQLRequest(request);
		if (result != null) {
			Iterator<List<Object>> it = result.iterator();
			while (it.hasNext()) {
				List<Object> next = it.next();
				this.graphComboBox.addItem(next.get(0), (String) next.get(1));
			}
		}
		this.connectionField.setText(connectionName);
		this.fileId = fileId;
		this.connectionId = -1;
		
		this.setVisible(true);
	}
	public void replace(int connectionId, String connectionName, int fileId, int graphId, String anchor) {
		// load data from model
		this.graphComboBox.removeAllItems();
		String request = "select s1.db_id, s1.name from graph s1;";
		List<List<Object>> result = param.graphDataBase.executeSQLRequest(request);
		if (result != null) {
			Iterator<List<Object>> it = result.iterator();
			while (it.hasNext()) {
				List<Object> next = it.next();
				this.graphComboBox.addItem(next.get(0), (String) next.get(1));
			}
		}
		this.connectionField.setText(connectionName);
		this.graphComboBox.selectObject(graphId);
		this.anchorComboBox.selectObject(anchor);
		this.fileId = fileId;
		this.connectionId = connectionId;

		this.setVisible(true); 
	}
	public void addConnection(String connectionName, String anchor, int graphId, String graphName, int fileId) {
		UIEventCreateNewConnection event = new UIEventCreateNewConnection(getNextId(), connectionName, anchor, graphId, graphName, fileId);
		this.param.userInterfaceManager.sendEvent(event);
	}
	/**
	 * This method updates user interface theme.
	 */
	public void updateUIThemes() {
		SwingUtilities.updateComponentTreeUI(this);
	}
	///////////////////////////////////////////////////////////////////////////
	// PRIVATE METHODS
	///////////////////////////////////////////////////////////////////////////
	/**
	 * This method returns next id for connect.
	 */
	private int getNextId() {
		int a = counterId.incrementAndGet();
		return(a);
	}
}
